//
// Created by 罗宋汤 on 15/8/29.
// Copyright (c) 2015 CHANJET. All rights reserved.
//

#import "CSPURLRequestSerialization.h"
#import "CSPTask.h"
#import "CSPGZIP.h"
#import "CSPLogging.h"
#import "CSPCategory.h"


@implementation CSPJSONRequestSerializer
- (CSPTask *)validateRequest:(NSURLRequest *)request {
    return [CSPTask taskWithResult:nil];
}

- (CSPTask *)serializeRequest:(NSMutableURLRequest *)request headers:(NSDictionary *)headers parameters:(NSDictionary *)parameters {
    request.cachePolicy = NSURLRequestReloadIgnoringLocalCacheData;

    NSError *error = nil;

    //construct HTTPBody only if HTTPBodyStream is nil
    if (!request.HTTPBodyStream) {
        NSData *bodyData = [NSJSONSerialization dataWithJSONObject:parameters
                                                           options:0
                                                             error:&error];
        if (!error) {
            if ([request.HTTPMethod isEqualToString:@"GET"]) {
                //GET request should be have any body. aws lambda server will close connection if that is the case.
                bodyData = nil;
            }
            if (headers[@"Content-Encoding"] && [headers[@"Content-Encoding"] rangeOfString:@"gzip"].location != NSNotFound) {
                //gzip the body
                request.HTTPBody = [bodyData cspgzip_gzippedData];
            } else {
                request.HTTPBody = bodyData;
            }
        }
    }

    CSPLogVerbose(@"Request body: [%@]", [[NSString alloc] initWithData:request.HTTPBody encoding:NSUTF8StringEncoding]);

    if (!error) {
        for (NSString *key in headers) {
            [request setValue:headers[key] forHTTPHeaderField:key];
        }

        return [CSPTask taskWithResult:nil];
    }

    return [CSPTask taskWithError:error];
}

@end

@implementation CSPQueryStringRequestSerializer

- (void)processParameters:(NSDictionary *)parameters queryString:(NSMutableString *)queryString {
    for (NSString *key in parameters) {
        id obj = parameters[key];

        if ([obj isKindOfClass:[NSDictionary class]]) {
            [self processParameters:obj queryString:queryString];
        } else {

            if ([queryString length] > 0) {
                [queryString appendString:@"&"];
            }

            if ([obj isKindOfClass:[NSString class]]) {
                [queryString appendString:[key csp_stringWithURLEncoding]];
                [queryString appendString:@"="];
                NSString *urlEncodedString = [obj csp_stringWithURLEncoding];
                [queryString appendString:urlEncodedString];
            } else if ([obj isKindOfClass:[NSNumber class]]) {
                [queryString appendString:[key csp_stringWithURLEncoding]];
                [queryString appendString:@"="];
                [queryString appendString:[[obj stringValue] csp_stringWithURLEncoding]];
            } else {
                CSPLogError(@"key[%@] is invalid.", key);
                [queryString appendString:[key csp_stringWithURLEncoding]];
                [queryString appendString:@"="];
                [queryString appendString:[[obj description] csp_stringWithURLEncoding]];
            }
        }
    }

}

- (CSPTask *)serializeRequest:(NSMutableURLRequest *)request
                      headers:(NSDictionary *)headers
                   parameters:(NSDictionary *)parameters {
    request.cachePolicy = NSURLRequestReloadIgnoringLocalCacheData;

    parameters = [parameters mutableCopy];
    [self.additionalParameters enumerateKeysAndObjectsUsingBlock:^(id key, id obj, BOOL *stop) {
        [parameters setValue:obj forKey:key];
    }];

    //Need to add version and actionName
//    NSError *error = nil;
    NSDictionary *formattedParams = parameters; //[CSPQueryParamBuilder buildFormattedParams:parameters
//                                                                    actionName:self.actionName
//                                                         serviceDefinitionRule:self.serviceDefinitionJSON error:&error];
//    if (error) {
//        return [CSPTask taskWithError:error];
//    }

    NSMutableString *queryString = [NSMutableString new];
    [self processParameters:formattedParams queryString:queryString];

    if ([queryString length] > 0) {
        request.HTTPBody = [queryString dataUsingEncoding:NSUTF8StringEncoding];
    }
    CSPLogVerbose(@"Request body: [%@]", [[NSString alloc] initWithData:request.HTTPBody
                                                               encoding:NSUTF8StringEncoding]);
    //contruct additional headers
    if (headers) {
        //generate HTTP header here
        for (NSString *key in headers.allKeys) {
            [request setValue:headers[key] forHTTPHeaderField:key];
        }
    }

    if (!request.allHTTPHeaderFields[@"Content-Type"]) {
        [request addValue:@"application/x-www-form-urlencoded; charset=utf-8"
       forHTTPHeaderField:@"Content-Type"];
    }

    return [CSPTask taskWithResult:nil];
}

- (CSPTask *)validateRequest:(NSURLRequest *)request {
    return [CSPTask taskWithResult:nil];
}

@end